package com.monkey.service;

import com.monkey.core.ErrorCode;
import com.monkey.core.WebRet;
import com.monkey.generator.dao.TAdminMapper;
import com.monkey.generator.dao.TUserDrawMapper;
import com.monkey.generator.model.TAdmin;
import com.monkey.generator.model.TAdminExample;
import com.monkey.generator.model.TUserDraw;
import com.monkey.generator.model.TUserDrawExample;
import com.monkey.model.admin.Admin;
import com.monkey.model.admin.AdminLoginData;
import com.monkey.model.admin.AdminToken;
import com.monkey.model.user.User;
import com.monkey.model.user.UserDrawData;
import com.monkey.util.DateUtil;
import com.monkey.util.IDGenerator;
import com.monkey.util.WebConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.monkey.service.MonkeyService.MONKEY_STATUS_NORMAL;
import static com.monkey.service.UserService.ACTION_ADMIN;
import static com.monkey.service.UserService.ACTION_DRAW;

/**
 * desc:
 * auth: chenxiaobin
 * data: 2018/1/16.
 */
@Service
@Transactional
public class AdminService {
    private static Logger logger = LoggerFactory.getLogger(AdminService.class);
    public static final int DRAW_ALL = 0; // 全部
    public static final int DRAW_WAIT = 1; // 请求提现
    public static final int DRAW_COMPLETE = 2; // 提现完成
    public static final int DRAW_CANCEL = 3; // 提现取消
    private Map<String, AdminToken> tokenMap = new HashMap<>();      // token
    private boolean allow;

    @Resource
    private UserService userService = null;

    @Resource
    private MonkeyService monkeyService = null;

    @Resource
    private BonusService bonusService = null;

    @Resource
    private TaskService taskService = null;

    @Resource
    private TAdminMapper adminMapper = null;

    @Resource
    private TUserDrawMapper userDrawMapper = null;

    @Resource
    private IDGenerator idGenerator = null;

    @Resource
    private DateUtil dateUtil = null;

    @Resource
    private WebConfig webConfig = null;

    public void init() {
        int enable = webConfig.getInt("system.login.enable");
        this.allow = (0 != enable);
    }

    public AdminLoginData login(String account, String password) {
        TAdminExample example = new TAdminExample();
        example.or().andAccountEqualTo(account).andPasswordEqualTo(password);
        example.setLimit(1);
        List<TAdmin> list = adminMapper.selectByExample(example);
        if (null == list || list.isEmpty()) {
            return new AdminLoginData(ErrorCode.USER_NO_EXIST);
        }
        String token = idGenerator.randomUUID();
        Admin admin = new Admin(list.get(0));
        insertToken(admin, token);
        return new AdminLoginData(ErrorCode.SUCCESS, token, admin);
    }

    public AdminToken getAdminWithToken(String token) {
        // 验证token
        AdminToken t;
        synchronized (this) {
            t = tokenMap.get(token);
        }
        if (null == t) {
            return null;
        }

        // TODO 超时检测
        // TODO 更新token过期时间

        return t;
    }

    public void insertToken(Admin admin, String token) {
        int timeout = webConfig.getInt("admin.token.timeout");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.HOUR_OF_DAY, timeout);
        AdminToken t = new AdminToken(token, admin.getAccount(), admin.getLevel(), calendar.getTime());
        synchronized (this) {
            tokenMap.put(token, t);
        }
    }

    public void deleteToken(String token) {
        synchronized (this) {
            tokenMap.remove(token);
        }
    }

    public boolean isAllow() {
        return allow;
    }

    public WebRet setAllow(boolean allow) {
        this.allow = allow;
        return new WebRet(ErrorCode.SUCCESS);
    }

    public WebRet shutdown() {
        logger.info("----------------------close start----------------------");
        taskService.close();
        logger.info("task service success");
        logger.info("----------------------close end----------------------");
        return new WebRet(ErrorCode.SUCCESS);
    }

    public WebRet drawMoney(int userId, float money) {
        SimpleDateFormat sdf = dateUtil.getSimpleDateFormat();
        SimpleDateFormat sdf2 = dateUtil.getDateFormat();
        Date now = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        calendar.add(Calendar.HOUR_OF_DAY, -24);
        String str1 = sdf.format(now) + " 23:59:59";
        String str2 = sdf.format(calendar.getTime()) + " 23:59:59";
        Date date1, date2;
        try {
            date1 = sdf2.parse(str1);
            date2 = sdf2.parse(str2);
        } catch (Exception e) {
            logger.info("draw money error from:{} to:{}", str2, str1);
            return new WebRet(ErrorCode.DRAW_HAS_EXIST);
        }

        // 一天只能有一个请求
        TUserDrawExample example = new TUserDrawExample();
        example.or().andUseridEqualTo(userId).andCreatetimeGreaterThan(date2).andCreatetimeLessThan(date1);
        example.setLimit(1);
        List<TUserDraw> draws = userDrawMapper.selectByExample(example);
        if (null != draws && !draws.isEmpty()) {
            return new WebRet(ErrorCode.DRAW_HAS_EXIST);
        }

        User user = userService.getUser(userId);
        if (null == user) {
            return new WebRet(ErrorCode.USER_NO_EXIST);
        }
        if (null == user.getWallet()) {
            return new WebRet(ErrorCode.WALLET_NO_BIND);
        }
        if (user.getMoney().floatValue() <= 0) {
            return new WebRet(ErrorCode.WALLET_LESS_ERROR);
        }

        TUserDraw draw = new TUserDraw();
        draw.setUserid(userId);
        draw.setWallet(user.getWallet());
        draw.setApply(new BigDecimal(money));
        draw.setStatus(DRAW_WAIT);
        draw.setCreatetime(new Date());
        userDrawMapper.insert(draw);
        return new WebRet(ErrorCode.SUCCESS);
    }

    public WebRet drawMoneyComplete(int userId) {
        TUserDrawExample example = new TUserDrawExample();
        example.or().andUseridEqualTo(userId).andStatusEqualTo(DRAW_WAIT);
        example.setLimit(1);
        List<TUserDraw> draws = userDrawMapper.selectByExample(example);
        if (null == draws || draws.isEmpty()) {
            return new WebRet(ErrorCode.DRAW_NO_EXIST);
        }

        User user = userService.getUser(userId);
        if (null == user) {
            return new WebRet(ErrorCode.USER_NO_EXIST);
        }
        BigDecimal money = user.getMoney();
        int ret = userService.updateUserMoney(user, 0, -money.floatValue(), 0, MONKEY_STATUS_NORMAL, ACTION_DRAW);
        if (ErrorCode.SUCCESS != ret) {
            return new WebRet(ret);
        }

        TUserDraw draw = new TUserDraw();
        draw.setMoney(money);
        draw.setStatus(DRAW_COMPLETE);
        userDrawMapper.updateByExampleSelective(draw, example);
        return new WebRet(ErrorCode.SUCCESS);
    }

    public WebRet drawMoneyCancel(int userId) {
        TUserDrawExample example = new TUserDrawExample();
        example.or().andUseridEqualTo(userId).andStatusEqualTo(DRAW_WAIT);
        example.setLimit(1);
        List<TUserDraw> draws = userDrawMapper.selectByExample(example);
        if (null == draws || draws.isEmpty()) {
            return new WebRet(ErrorCode.DRAW_NO_EXIST);
        }

        TUserDraw draw = new TUserDraw();
        draw.setStatus(DRAW_CANCEL);
        userDrawMapper.updateByExampleSelective(draw, example);
        return new WebRet(ErrorCode.SUCCESS);
    }

    public UserDrawData getDrawList(int offset, int num, int status) {
        TUserDrawExample example = new TUserDrawExample();
        if (DRAW_ALL != status) {
            example.or().andStatusEqualTo(status);
        }

        int total = (int) userDrawMapper.countByExample(example);
        example.setOffset(offset);
        example.setLimit(num);
        List<TUserDraw> draws = userDrawMapper.selectByExample(example);
        if (null == draws || draws.isEmpty()) {
            return new UserDrawData(ErrorCode.DRAW_NO_EXIST);
        }
        return new UserDrawData(ErrorCode.SUCCESS, total, draws);
    }
}
